/*
 * TcpReader.cpp
 *
 *  Created on: 2009-8-20
 *      Author: fanliangliang
 */

#include "TcpReader.h"
#include "SocketListener.h"
#include "TimeoutTimer.h"

CTcpReader* CTcpReader::NewL(MSocketListener& aListener, RSocket& aSocket) {
	CTcpReader* self = NewLC(aListener, aSocket);
	CleanupStack::Pop(self);
	return self;
}

CTcpReader* CTcpReader::NewLC(MSocketListener& aListener, RSocket& aSocket) {
	CTcpReader* self = new (ELeave) CTcpReader(aListener, aSocket);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
}

CTcpReader::CTcpReader(MSocketListener& aListener, RSocket& aSocket)
:CActive(EPriorityStandard)
,iListener(aListener)
,iSocket(aSocket)
,iTimer(NULL)
,iTimeout(KDefaultTimeoutInSeconds) {
	CActiveScheduler::Add(this);
}

CTcpReader::~CTcpReader() {
	Cancel();
	delete iTimer;
}

void CTcpReader::ConstructL() {
	iTimer = CTimeoutTimer::NewL(*this);
}

void CTcpReader::IssueRead() {
	if (!IsActive()) {
		iBuffer.Zero();
		iSocket.RecvOneOrMore(iBuffer, 0, iStatus, iDummyLength);
		// Request timeout
		iTimer->After(iTimeout);
		SetActive();
	}
}

void CTcpReader::SetTimeout(TTimeIntervalSeconds aTimeout) {
	iTimeout = aTimeout;
}

TTimeIntervalSeconds CTcpReader::Timeout() const {
	return iTimeout;
}

void CTcpReader::DoCancel() {
	iSocket.CancelRead();
	iTimer->Cancel();
}

void CTcpReader::RunL() {
	iTimer->Cancel();
	
	switch (iStatus.Int()) {
	case KErrNone:
		iListener.OnReceived(iBuffer);
		break;

	case KErrEof:
	case KErrDisconnected:
		iListener.OnSocketError(ERemoteHostClosed);
		break;

	default:
		iListener.OnSocketError(EReadError);
		break;
	}
}

void CTcpReader::OnTimerExpired() {
	Cancel();
	iListener.OnSocketError(EReadTimeout);
}
